package org.uned.agonzalo16.bitacora.service.search;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.uned.agonzalo16.bitacora.dao.ArticleDao;
import org.uned.agonzalo16.bitacora.dao.BlogDao;
import org.uned.agonzalo16.bitacora.domain.Article;
import org.uned.agonzalo16.bitacora.domain.Blog;

import com.google.appengine.api.search.Document;
import com.google.appengine.api.search.Field;
import com.google.appengine.api.search.Index;
import com.google.appengine.api.search.IndexSpec;
import com.google.appengine.api.search.Results;
import com.google.appengine.api.search.ScoredDocument;
import com.google.appengine.api.search.SearchServiceFactory;

public class SearchService {

	private static final String ARTICLE_INDEX_NAME = "ARTICLE_INDEX_NAME";
	private static final String BLOG_INDEX_NAME = "BLOG_INDEX_NAME";

	@Autowired
	private ArticleDao articleDao;

	@Autowired
	private BlogDao blogDao;

	private boolean initedIndex = false;

	private Index getArticleIndex() {
		IndexSpec indexSpec = IndexSpec.newBuilder().setName(ARTICLE_INDEX_NAME).build();
		return SearchServiceFactory.getSearchService().getIndex(indexSpec);
	}

	private Index getBlogIndex() {
		IndexSpec indexSpec = IndexSpec.newBuilder().setName(BLOG_INDEX_NAME).build();
		return SearchServiceFactory.getSearchService().getIndex(indexSpec);
	}

	private void initIndex() {
		if (initedIndex) {
			return;
		}
		Index index1 = getArticleIndex();

		for (Article article : articleDao.findAll()) {
			index1.put(createDocument(article));
		}

		Index index2 = getBlogIndex();

		for (Blog blog : blogDao.findAll()) {
			index2.put(createDocument(blog));
		}

		initedIndex = true;
	}

	public void addArticle(Article article) {
		initIndex();
		Index index = getArticleIndex();
		index.put(createDocument(article));
	}

	public void addBlog(Blog blog) {
		initIndex();
		Index index = getBlogIndex();
		index.put(createDocument(blog));
	}

	public void removeArticle(Long articleId) {
		initIndex();
		Index index = getArticleIndex();
		index.delete(String.valueOf(articleId));
	}

	public void removeBlog(Long blogId) {
		initIndex();
		Index index = getBlogIndex();
		index.delete(String.valueOf(blogId));
	}

	public List<Article> searchArticles(String query) {
		initIndex();
		Index index = getArticleIndex();

		Results<ScoredDocument> indexResult = index.search(query);

		List<Article> articles = new ArrayList<Article>();
		for (ScoredDocument doc : indexResult) {
			Long articleKey = Long.valueOf(doc.getId());
			articles.add(articleDao.get(articleKey));
		}

		return articles;
	}

	public List<Blog> searchBlogs(String query) {
		initIndex();
		Index index = getBlogIndex();

		Results<ScoredDocument> indexResult = index.search(query);

		List<Blog> blogs = new ArrayList<Blog>();
		for (ScoredDocument doc : indexResult) {
			Long blogKey = Long.valueOf(doc.getId());
			blogs.add(blogDao.get(blogKey));
		}

		return blogs;
	}

	private Document createDocument(Article article) {
		Document doc = Document.newBuilder().setId(String.valueOf(article.getId())).addField(Field.newBuilder().setName("content").setText(article.getText()))
				.addField(Field.newBuilder().setName("title").setText(article.getTitle())).build();

		return doc;
	}

	private Document createDocument(Blog blog) {
		Document doc = Document.newBuilder().setId(String.valueOf(blog.getId())).addField(Field.newBuilder().setName("name").setText(blog.getName()))
				.addField(Field.newBuilder().setName("description").setText(blog.getDescription())).build();

		return doc;
	}

}
